import re

import networkx as nx

from app.Package.steinertree.Steinertree.steinertree_nodes import steinertree_nodes
from app.Package.steinertree.Tool.getterminal_node_id import getterminal_node_id
from app.Package.steinertree.Tool.readname import readname
from app.Package.steinertree.Tool.readnet import readnet
from app.Package.steinertree.Tool.symMatrix import symMatrix
from app.Vendor.ApiException import illegalCpdErr


class SteinterTreeService:
    def getPathway(self, input_list):
        itera_num = 1

        # 1.输入差异代谢物
        terminal_nodes_name = input_list
        # 2.导入基础网络

        load = "app/Package/steinertree/Dataset/KEGG_ReactionNet/KEGG_ReactionNet_name.xlsx"
        indexname = 'name'

        KEGG_ReactionNet_name = readname(load, indexname)

        load5 = "app/Package/steinertree/Dataset/KEGG_ReactionNet/KEGG_ReactionNet.xlsx"
        bnet = symMatrix(readnet(load5))  # 对称矩阵

        G = nx.from_numpy_array(bnet)
        largest = max(nx.connected_components(G), key=len)
        GG = G.subgraph(largest)

        KEGG_largest_Net_namelist = [KEGG_ReactionNet_name[i] for i in GG.nodes()]  # 最大联通子图 的名字
        GGedgesName = [(KEGG_ReactionNet_name[i[0]], KEGG_ReactionNet_name[i[1]]) for i in GG.edges()]

        terminal_nodes = getterminal_node_id(terminal_nodes_name, KEGG_ReactionNet_name)  # 获取差异边在联通网路中的id

        # 3.执行斯坦纳树

        stEdges = steinertree_nodes(itera_num, GG, terminal_nodes)

        SteinerTreeNet = GG.edge_subgraph(stEdges)
        SteinerNodes = [i for i in SteinerTreeNet.nodes() if i not in terminal_nodes]
        SteinerNodesName = [KEGG_ReactionNet_name[i] for i in SteinerNodes]

        AllcpdName = [KEGG_ReactionNet_name[i] for i in SteinerTreeNet.nodes()]


        Interaction = [(KEGG_ReactionNet_name[i[0]], KEGG_ReactionNet_name[i[1]]) for i in SteinerTreeNet.edges()]

        interaction_list = []

        for i in Interaction:
            if i[0] > i[1]:
                interaction_list.append([i[1], i[0]])
            elif i[0] < i[1]:
                interaction_list.append([i[0], i[1]])

        # 返回所有cpd的名字列表和反应对的列表
        return AllcpdName, interaction_list

    def splitText(self, text):
        # 按照换行符进行切割,并检验输入是否合法
        lines = text.splitlines()
        lines_set = set()
        for line in lines:
            line = str(line).strip()
            line = line.upper()
            if (re.search(r'^C\d{5}$', line) is None):
                raise illegalCpdErr()
            lines_set.add(line)
        return lines_set
